package common;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class Auction implements Sendable,Comparable<Auction> {
	private static final long serialVersionUID = -7050214304337357549L;
	public final String ownerName;
	
	public final Commodity commodity;
	public final double price;
	public final int quantity;
	public final long duration;
	public final TimeUnit time;
	
	private int uniqueID;
	
	private final AtomicBoolean isScheduled = new AtomicBoolean( false );
	private transient volatile ScheduledFuture<?> scheduledExpiration = null;
	
	private transient static final AtomicInteger auctionCounter = new AtomicInteger(0);

	public Auction( String owner, Commodity commodity, double price, int quantity, long duration, TimeUnit time ) {
		this.ownerName = owner;
		this.commodity = commodity;
		this.price = price;
		this.quantity = quantity;
		this.duration = duration;
		this.time = time;
	}
	
	public abstract boolean isValid( double price, int quantity );
	public abstract boolean isValidMatch(Auction a);
	public abstract boolean isValid( CommodityLimits L);

	public boolean invalidCommodity() {
		return commodity == null;
	}
	
	public boolean overQuantity( int q ) {
		return quantity > q;
	}
	
	public double getMatchPrice (Auction a) {
		return (a.price + this.price)/2;
	}
	
	public int hashCode () {
		return uniqueID;
	}
	public boolean equals(Object a) {
		return (a instanceof Auction) ? equals((Auction)a) : false;
	}
	public boolean equals(Auction a) {
		return uniqueID == a.uniqueID;
	}
	
	public void generateID() {
		uniqueID = auctionCounter.getAndIncrement();
	}
	
	public boolean setScheduled() {
		return isScheduled.compareAndSet( false, true );
	}
	
	public boolean isScheduled() {
		return isScheduled.get();
	}
	
	public void setScheduledFuture( ScheduledFuture<?> future ) {
		scheduledExpiration = future;
	}
	
	public boolean cancelExpiration() {
		return ( scheduledExpiration != null) ? scheduledExpiration.cancel( true ) : false;
	}
	
	public String toString() {
		return commodity + ":   \t$" + AllTheEvilsOfThisWorld.obfuscateNumber(price) + "/unit   \t#" + quantity + " units";
	}
	
	public int compareTo(Auction a) {
		return (price > a.price) ? -1 : 1;
	}
}
